/* 
 * This code is part of the notepad application, a sample application
 * for the SmartLink project, see
 * 
 * 		http://code.google.com/p/smartlink/.
 * 
 * It is a slightly modified version of the original notepad sample application 
 * distributed by Google as part of the Android SDK, see
 * 
 * 		http://code.google.com/android/samples/NotePad/index.html.
 * 
 * The modifications have the purpose of making the notepad application
 * acting as a "smartlink client" and "smartlink server" application.
 * What this means and the necessary requirements can be found in the documentation
 * of the SmartLink project. 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.android.notepad;

import org.smartlink.Server;

import android.app.ListActivity;
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.MeasureSpec;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;

import com.google.provider.NotePad;

/**
 * Displays a list of notes. Will display notes from the ContentUri provided int
 * the intent if there is one, otherwise uses the default list from the
 * 
 */
public class NotesList extends ListActivity {

	// private static final String TAG = "NotesList";

	// Menu item Ids
	public static final int DELETE_ID = Menu.FIRST;
	public static final int INSERT_ID = Menu.FIRST + 1;

	/**
	 * The columns we are interested in from the database
	 */
	private static final String[] PROJECTION = new String[] { NotePad.Notes._ID, NotePad.Notes.TITLE };

	/**
	 * Cursor which holds list of all notes
	 */
	private Cursor mCursor;

	@Override
	protected void onCreate(Bundle icicle) {
		super.onCreate(icicle);

		setDefaultKeyMode(SHORTCUT_DEFAULT_KEYS);

		// If no data was given in the intent (because we were started
		// as a MAIN activity), then use our default content provider.
		Intent intent = getIntent();
		if (intent.getData() == null) {
			intent.setData(NotePad.Notes.CONTENT_URI);
		}
		intent.setData(NotePad.Notes.CONTENT_URI);
		setupListStripes();
		mCursor = managedQuery(getIntent().getData(), PROJECTION, null, null);
		// Used to map notes entries from the database to views
		ListAdapter adapter = new SimpleCursorAdapter(this, R.layout.noteslist_item, mCursor,
				new String[] { NotePad.Notes.TITLE }, new int[] { android.R.id.text1 });
		setListAdapter(adapter);
	}

	/**
	 * Add stripes to the list view.
	 */
	private void setupListStripes() {
		// Get Drawables for alternating stripes
		Drawable[] lineBackgrounds = new Drawable[2];

		lineBackgrounds[0] = getResources().getDrawable(R.drawable.even_stripe);
		lineBackgrounds[1] = getResources().getDrawable(R.drawable.odd_stripe);

		// Make and measure a sample TextView of the sort our adapter will
		// return
		View view = getViewInflate().inflate(android.R.layout.simple_list_item_1, null, null);

		TextView v = (TextView) view.findViewById(android.R.id.text1);
		v.setText("X");
		// Make it 100 pixels wide, and let it choose its own height.
		v.measure(MeasureSpec.makeMeasureSpec(View.MeasureSpec.EXACTLY, 100), MeasureSpec.makeMeasureSpec(
				View.MeasureSpec.UNSPECIFIED, 0));
		int height = v.getMeasuredHeight();
		getListView().setStripes(lineBackgrounds, height);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);

		// This is our one standard application action -- inserting a
		// new note into the list.
		menu.add(0, INSERT_ID, R.string.menu_insert).setShortcut('3', 'a');

		// Generate any additional actions that can be performed on the
		// overall list. In a normal install, there are no additional
		// actions found here, but this allows other applications to extend
		// our menu with their own actions.
		Intent intent = new Intent(null, getIntent().getData());
		intent.addCategory(Intent.ALTERNATIVE_CATEGORY);
		menu.addIntentOptions(Menu.ALTERNATIVE, 0, new ComponentName(this, NotesList.class), null, intent, 0, null);

		return true;
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		super.onPrepareOptionsMenu(menu);
		final boolean haveItems = mCursor.count() > 0;

		// If there are any notes in the list (which implies that one of
		// them is selected), then we need to generate the actions that
		// can be performed on the current selection. This will be a combination
		// of our own specific actions along with any extensions that can be
		// found.
		if (haveItems) {
			// This is the selected item.
			Uri uri = ContentUris.withAppendedId(getIntent().getData(), getSelectedItemId());

			// Build menu... always starts with the EDIT action...
			Intent[] specifics = new Intent[1];
			specifics[0] = new Intent(Intent.EDIT_ACTION, uri);
			Menu.Item[] items = new Menu.Item[1];

			// ... is followed by whatever other actions are available...
			Intent intent = new Intent(null, uri);
			intent.addCategory(Intent.SELECTED_ALTERNATIVE_CATEGORY);
			menu.addIntentOptions(Menu.SELECTED_ALTERNATIVE, 0, null, specifics, intent, 0, items);

			// ... and ends with the delete command.
			menu.add(Menu.SELECTED_ALTERNATIVE, DELETE_ID, R.string.menu_delete).setShortcut('2', 'd');

			// Give a shortcut to the edit action.
			if (items[0] != null) {
				items[0].setShortcut('1', 'e');
			}
		} else {
			menu.removeGroup(Menu.SELECTED_ALTERNATIVE);
		}

		// Make sure the delete action is disabled if there are no items.
		menu.setItemShown(DELETE_ID, haveItems);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(Menu.Item item) {
		switch (item.getId()) {
		case DELETE_ID:
			deleteItem();
			return true;
		case INSERT_ID:
			insertItem();
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		Uri url = ContentUris.withAppendedId(getIntent().getData(), id);

		String action = getIntent().getAction();
		if (Intent.PICK_ACTION.equals(action) || Intent.GET_CONTENT_ACTION.equals(action)) {
			// The caller is waiting for us to return a note selected by
			// the user. He has clicked on one, so return it now.
			setResult(RESULT_OK, url.toString());
		} else if (Server.PICK_TARGET_ACTION.equals(action)) {
			// smartlink-server: smartlink is waiting for us to return a url to
			// a note
			Bundle bundle = new Bundle(2);
			bundle.putString(Server.EXTRA_ITEM_DESCRIPTION, getDescription(url));
			bundle.putString(Server.EXTRA_ITEM_TARGET, url.toString());
			setResult(RESULT_OK, url.toString(), bundle);
			finish();
		} else {
			// Launch activity to view/edit the currently selected item
			startActivity(new Intent(Intent.EDIT_ACTION, url));
		}
	}

	/** gets a description of the picked contact. */
	private String getDescription(Uri uri) {
		// An array specifying which columns to return.
		String[] projection = new String[] { NotePad.Notes.NOTE };

		Cursor cur = managedQuery(uri, projection, // Which columns to return.
				null, // WHERE clause--we won't specify.
				null); // Order-by clause.
		if (!cur.first()) {
			return null;
		}
		int noteContent = cur.getColumnIndex(NotePad.Notes.NOTE);
		// TODO: maybe cut off more intelligently?
		String note = cur.getString(noteContent);
		return (note.length() > 30) ? note.substring(0, 30) + "..." : note;
	}

	private final void deleteItem() {
		mCursor.moveTo(getSelectedItemPosition());
		mCursor.deleteRow();
	}

	private final void insertItem() {
		// Launch activity to insert a new item
		startActivity(new Intent(Intent.INSERT_ACTION, getIntent().getData()));
	}
}
